(* ==========================================================================
     Simple Streams library test app
     Version 0.95, Freeware
   --------------------------------------------------------------------------
     (c) 2012, TSX Software
   ========================================================================== *)
program test;

{$APPTYPE CONSOLE}

uses
  Windows,
  SysUtils,
  ActiveX,
  uLSLibImp in 'uLSLibImp.pas';

function iStr(i: integer; d: integer = 0): string;
begin
  Str(i, Result);
  if (d>0) then while (length(Result)<d) do
    Result := '0'+Result;
end;

function FileTimeToStr(ff: FILETIME): string;
var st: SYSTEMTIME;
begin
  FileTimeToSystemTime(ff, st);
  Result :=
    iStr(st.wHour,2)+':'+iStr(st.wMinute,2)+':'+iStr(st.wSecond,2)+'.'+
    iStr(st.wMilliseconds,3)+' '+
    iStr(st.wDay,2)+'.'+iStr(st.wMonth,2)+'.'+iStr(st.wYear,4);
end;

var strm, ms: HLSTREAM;
    istrm, ims: IStream;
    nPos,rd,wrt: int64;
    stat: TStatStg;
    res: HResult;

    buf: array[0..1023] of byte;
    i: integer;
begin
  WriteLn('Library version: ',lsStreamVersion);

  if not FileExists('test_file.001') then begin
    res := lsStreamCreateFile(PWideChar(widestring('test_file.001')), STRM_UNICODE, 0, strm);
    if (res=S_OK) then begin
      for i := Low(buf) to High(buf) do
        buf[i] := Random(255);
      res := lsStreamWrite(strm, buf[0], sizeOf(buf), nil);
      if (res<>S_OK) then writeLn(Format('Write error: %.8x', [res]));
      lsStreamFree(strm);
    end else
      writeLn(Format('Create file error: %.8x', [res]));
  end;

  // Test for file open
  res := lsStreamOpenFile(PWideChar(widestring('test_file.001')), STRM_UNICODE, GENERIC_READ, 0, strm);
  if (res=S_OK) then begin
    writeln('File opened');

    // Testing Seek func in GetSize macro (Size property)
    lsStreamGetSize(strm, nPos);
    writeln('Size: ', nPos, ' bytes');

    // Testing Seek func (Position property)
    lsStreamSeek(strm, $1000, STREAM_SEEK_SET, nPos);
    lsStreamSeek(strm, 0, STREAM_SEEK_CUR, nPos);
    writeln('Position: ', nPos, ' bytes');

    // Demo of IStream interface handling
    if lsStreamQueryInterface(strm, IID_IStream, istrm)=S_OK then begin
      // For file streams Stat method is implemented
      if istrm.Stat(stat, STATFLAG_DEFAULT) = S_OK then begin
        writeLn('Stats:');
        if (stat.pwcsName<>nil) then begin
          writeLn('  ',widestring(stat.pwcsName));
          // Do not forget to free string
          SysFreeString(stat.pwcsName);
        end;
        writeln('  Created    : ', FileTimeToStr(stat.ctime));
        writeln('  Modified   : ', FileTimeToStr(stat.mtime));
        writeln('  Last access: ', FileTimeToStr(stat.atime));
      end;

      // So you can use this interface as you use TStream class
      //strm.Seek(0, STREAM_SEEK_SET, nPos);
      // note: you can set pcbRead param to nil if you dont' need to know
      // how many bytes were read
      //if strm.Read(@buf, dwBufSize, @dwReadSize)=S_OK then ...;

      writeLn('Trying stream-copy...');
      res := lsStreamCreateFile(PChar('test_file.002'), 0,0, ms);
      if (res=S_OK) then begin
        if (lsStreamQueryInterface(ms, IID_IStream, ims)=S_OK) then begin
          if istrm.CopyTo(ims, -1, rd, wrt) = S_OK then begin
            writeLn('Copied OK, ',rd,' bytes read, ', wrt,' bytes written');
          end;
          ims := nil;
        end;
        lsStreamFree(ms);
      end;
      // Do not forget release interfaces, even in non-reference-counted version.
      istrm := nil;
    end;

    // Freeing stream
    lsStreamFree(strm);
    if strm=nil then Writeln('closed');
  end else
    writeLn('Failed to open file! Error '+Format('%.8x', [res]));

  WriteLn('Press ENTER to exit.');
  readln;
end.
